package Server.junit;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Vector;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import Server.Game;
import Server.map.Map;

import common.Ranking;
import common.UserMap;
import common.exception.BusyNameException;
import common.exception.FailedAuthenticationException;
import common.exception.FullMatchException;
import common.exception.InvalidTokenException;

public class GameTest {

	private static Game g;
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		g = Game.getGame();
		g.useMapData("ciao.dat");
		try{
			g.newUser("pippo", "pluto");
		} catch(Exception e){
			fail();
		}
	}

	@Before
	public void setUp() throws Exception {
		g = Game.getGame();
	}


	@Test
	public void testGetGame() {
		assertNotNull(g);
	}

	@Test
	public void testUseMapData() {
		g.useMapData("ciao.dat");
	}

	@Test
	public void testLogin() {
		try{
			int token = g.login("pippo", "pluto");
			assertTrue(token >= 0);
		} catch (FailedAuthenticationException e){
			fail();
		}
	}

	@Test
	public void testNewSpecies() {
		int token = 0;
		try{
			g.newSpecies(token, "specie", 'c');
			fail();
		} catch(InvalidTokenException e){
			try{
				token = g.login("pippo", "pluto");
				g.newSpecies(token, "specie", 'c');
			} catch (FailedAuthenticationException e1){
				fail();
			} catch(BusyNameException e2){
				fail();
			} catch(InvalidTokenException e3){
				fail();
			}
		} catch(BusyNameException e){
			fail();
		}
	}

	@Test
	public void testNewUser() {
		try{
			g.newUser("foo", "bar");
		} catch (BusyNameException e){
			fail();
		}
	}
	
	@Test
	public void testGetPlayers() {
		try{
			int token = g.login("pippo", "pluto");
			int token1 = g.login("foo", "bar");
			g.newSpecies(token1, "foo", 'c');
			g.inGame(token);
			g.inGame(token1);
			
			String[] s = {"pippo", "foo"};
			assertEquals(s[0], g.getPlayers(token)[0]);
			assertEquals(s[1], g.getPlayers(token)[1]);
		} catch(Exception e){
			fail();
		}
	}
	

	@Test
	public void testInGame() {
		int token = 0, token1 = 0, token2 = 0, token3 = 0, token4 = 0, token5 = 0, token6 = 0, token8 = 0;
		try{
			g.inGame(token);
			fail();
		} catch(InvalidTokenException e){
			try{
				//SUCCESSO
				try{
					g.newUser("pippo1", "pluto1");
					token1 = g.login("pippo1", "pluto1");
					g.newSpecies(token1, "pippo1", 'c');
					g.inGame(token1);
					g.newUser("pippo2", "pluto2");
					token2 = g.login("pippo2", "pluto2");
					g.newSpecies(token2, "pippo2", 'c');
					g.inGame(token2);
					g.newUser("pippo3", "pluto3");
					token3 = g.login("pippo3", "pluto3");
					g.newSpecies(token3, "pippo3", 'c');
					g.inGame(token3);
					g.newUser("pippo4", "pluto4");
					token4 = g.login("pippo4", "pluto4");
					g.newSpecies(token4, "pippo4", 'c');
					g.inGame(token4);
					g.newUser("pippo5", "pluto5");
					token5 = g.login("pippo5", "pluto5");
					g.newSpecies(token5, "pippo5", 'c');
					g.inGame(token5);
					g.newUser("pippo6", "pluto6");
					token6 = g.login("pippo6", "pluto6");
					g.newSpecies(token6, "pippo6", 'c');
					g.inGame(token6);
					// PIENA
					g.newUser("pippo8", "pluto8");
					token8 = g.login("pippo8", "pluto8");
					g.newSpecies(token8, "pippo8", 'c');
					g.inGame(token8);
					fail();
				} catch (FailedAuthenticationException e1){
					fail();
				} catch(BusyNameException e3){
					fail();
				} catch(FullMatchException e2){
					g.outGame(token6);
					g.outGame(token5);
					g.outGame(token4);
					g.outGame(token3);
					g.outGame(token2);
					g.outGame(token1);
				}
			} catch(InvalidTokenException e3){
				fail();
			}
		} catch(FullMatchException e){
			fail();
		}
	}

	@Test
	public void testOutGame() {
		int token = 0;
		try{
			g.outGame(token);
			fail();
		} catch(InvalidTokenException e){
			try{
				token = g.login("pippo", "pluto");
				g.outGame(token);
				g.inGame(token);
				g.outGame(token);
			} catch (FailedAuthenticationException e1){
				fail();
			} catch(InvalidTokenException e2){
				fail();
			} catch(FullMatchException e3){
				fail();
			}
		}
	}


	@Test
	public void testLogout() {
		try{
		int token = g.login("foo", "bar");
		g.logout(token);
		} catch (Exception e){
			fail();	
		}
	}

	@Test
	public void testGetRanking() {
		try{
			int token = g.login("pippo", "pluto");
			Ranking r = g.getRanking(token);
			r.getRank(9);
		} catch (Exception e){
				fail();	
		}
	}

	@Test
	public void testGetMap() {
		try{
			int token = g.login("pippo", "pluto");
			g.inGame(token);
			UserMap map = g.getMap(token);
			assertNotNull(map);
			
		} catch (Exception e){
				fail();	
		}
	}
	
	@Test
	public void testGetDinoList() {
		try{
			int token = g.login("foo", "bar");
			g.inGame(token);
			Integer[] ids = g.getDinoList(token);
			assertNotNull(ids);
			assertTrue(ids.length == 1);
		} catch (Exception e){
				fail();	
		}
	}

	@Test
	public void testGetDinoStat() {
		try{
			int token = g.login("pippo", "pluto");
			g.inGame(token);
			Vector<Object> v = g.getDinoStat(token, 1);
			assertNotNull(v);	
			assertTrue(v.get(0) instanceof String);
			assertTrue(v.get(1) instanceof String);
			assertNotNull(v.get(2));
			assertTrue((Integer)v.get(3) >= 0 && (Integer)v.get(3) <= Map.SIZE);
			assertTrue((Integer)v.get(4) >= 0 && (Integer)v.get(4) <= Map.SIZE);
			assertTrue((Integer)v.get(5) >= 0  && (Integer)v.get(5) <= 5);
			assertTrue((Integer)v.get(6) >= 0);
			assertTrue((Integer)v.get(7) >= 0);
		} catch (Exception e){
				fail();	
		}
	}

	@Test
	public void testGetDinoVisual() {
		try{
			int token = g.login("pippo", "pluto");
			g.inGame(token);
			UserMap m = g.getDinoVisual(token, 1);
			assertNotNull(m);
		} catch (Exception e){
				fail();	
		}
	}


	@Test
	public void testUseTurn() {
		try{
			int token1 = g.login("foo", "bar");
			
			g.useTurn(token1);
		} catch (Exception e){
				fail();	
		}
	}
	
	@Test
	public void testSkipTurn() {
		try{
			int token1 = g.login("foo", "bar");
			
			g.skipTurn(token1);
		} catch (Exception e){
				fail();	
		}
	}
	

}
